package org.simpleFramework.mvc;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.simpleFramework.mvc.processor.RequestProcessor;
import org.simpleFramework.mvc.render.ResultRender;
import org.simpleFramework.mvc.render.impl.DefaultResultRender;
import org.simpleFramework.mvc.render.impl.InternalErrorResultRender;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Iterator;

/**
 * @description:
 * @author: air
 * @create: 2020-05-14 14:36
 */
@Data
@Slf4j
public class RequestProcessorChain {

    private Iterator<RequestProcessor> requestProcessorIterator;
    private HttpServletRequest request;
    private HttpServletResponse response;
    private String requestMethod;
    private String requestPath;
    private int responseCode;
    private ResultRender resultRender;


    public RequestProcessorChain(Iterator<RequestProcessor> iterator, HttpServletRequest req, HttpServletResponse resp) {
        this.requestProcessorIterator=iterator;
        this.request=req;
        this.response=resp;

        this.requestMethod=req.getMethod();
        this.requestPath=req.getPathInfo();
        this.responseCode=HttpServletResponse.SC_OK;
    }

    public void doRequestProcessorChain() {
        // 通过迭代器遍历注册的请求处理器实现类列表
        try{
            while (requestProcessorIterator.hasNext()){
                // 直到某个请求处理器执行后返回false为止
                if(!requestProcessorIterator.next().process(this)){
                    break;
                }
            }
        }catch (Exception e){
            // 期间如果出现异常，则交由内部处理异常渲染器处理
            this.resultRender=new InternalErrorResultRender(e.getLocalizedMessage());
            log.error("doRequestProcessorChain error");
        }
    }

    public void doRender() {
        // 如果请求器处理实现类均未选择合适的渲染器，则使用默认
        if (this.resultRender==null){
            this.resultRender=new DefaultResultRender();
        }

        // 调用渲染器的render方法对结果进行渲染
        try {
            this.resultRender.render(this);
        } catch (Exception e) {
            log.error("doRender error:",e);
            throw new RuntimeException(e);
        }
    }
}
